#!/usr/bin/env python
#coding=utf-8


import datetime
import pandas as pd
from app.bill.models.bill_instance import BillInstance
from app.bill.models.bill_month import BillMonth


from sqlalchemy.orm import Session
from core.response import resp_500
from core.logger import logger
from common.utils import is_empty


class BillMonthHandler(object):
    def __init__(self):
        pass


    def get_month_search(self, db: Session, page: int, per_page: int, field: str, value: str):
        """
        月度账单表, 根据表字段-模糊查询, 获取账单月度数据
        """
        try:
            field_info = {field: value}
            order_info = {"bill_cycle": "asc", "cloud_platform": "asc"}
            result = BillMonth.filter_by_field_search(db, page, per_page, field_info, order_info)
            if not result:
                logger.warning(f"get month search, result is null => {field}:{value}")
                return False

        except Exception as e:
            message = f"get month search by {field}:{value} error"
            logger.exception(f"{message} => {e}")
            return resp_500(message)

        return result



    def get_month_match(self, db: Session, page: int, per_page: int, field: str, value: str):
        """
        月度账单表, 根据表字段-完全查询, 获取账单月度数据
        """
        try:
            result = BillMonth.filter_by_field_match(db, page, per_page, {field: value})
            if not result:
                logger.warning(f"get month match failed, result is null => {field}:{value}")
                return False

        except Exception as e:
            message = f"get month match by {field}:{value} error"
            logger.exception(f"{message} => {e}")
            return resp_500(message)

        return result



    def add_month(self, db: Session, data: dict):
        """
        增加单个月度账单信息
        """
        try:
            bill_month_object = BillMonth.get_object_by_bill_cycle(db, data["bill_cycle"], data["cloud_platform"])
            if bill_month_object:
                # 如果存在， 则异常返回
                logger.error(f"add bill month failed, name:{data['bill_cycle']} was exist")
                return False

            # 添加到数据库
            result = BillMonth.add(db, data)
            if not result:
                logger.error(f"add bill month to database failed")
                return False
        except Exception as e:
            message = f"add bill month error"
            logger.exception(f"{message} data:{data} => {e}")
            return resp_500(message)

        return True



    def update_month(self, db: Session, data: dict):
        """
        修改单个账单月度信息
        """
        try:
            bill_month_object = BillMonth.get_object_by_uuid(db, data["uuid"])
            if not bill_month_object:
                # 如果不存在， 则异常返回
                logger.error(f"update bill month failed, uuid:{data['uuid']} not exist")
                return False

            # 去除comment的无效更新
            if "comment" in data and not data["comment"]:
                data.pop("comment")
                
            # 计算预算的税后金额
            data["tax_budget"] = round(data["budget_amount"] / 1.06, 2)
            
            # 更新数据库
            result = BillMonth.update(db, data)
            if not result:
                logger.error(f"update bill month to database failed")
                return False
        except Exception as e:
            message = f"update bill month error "
            logger.exception(f"{message} data:{data} => {e}")
            return resp_500(message)

        return True



    def delete_month(self, db: Session, data: dict):
        """
        删除账单月度信息
        """
        try:
            bill_month_object = BillMonth.get_object_by_uuid(db, data['uuid'])
            if not bill_month_object:
                # 如果不存在， 则异常返回
                logger.error(f"delete bill month failed, uuid:{data['uuid']} not exist")
                return False

            # 删除
            BillMonth.delete_object_by_uuid(db, data['uuid'])
        except Exception as e:
            message = f"delete bill month error"
            logger.exception(f"{message} data:{data} => {e}")
            return resp_500(message)

        return True


    def get_one_year(self, db: Session, year: str):
        """
        获取一整年的账单月度信息
        """
        try:
            # 获取这一年所有的月份
            months = self.get_all_months(year)

            result = BillMonth.get_months(db, months)
        except Exception as e:
            message = f"delete bill month error"
            logger.exception(f"{message} year:{year} => {e}")
            return resp_500(message)

        return result




    def get_months(self, year=None):
        """
        根据年份，获取实际存在账单的月份数，方便批量导入一年的账单数据
        """

        # 本月, 月初5个工作日后, 才会出上个月的账单数据
        current_date = datetime.datetime.today() - datetime.timedelta(days=7)
        # 上月, 只能查到上月的账单
        last_date = datetime.date(current_date.year, current_date.month, 1) - datetime.timedelta(days=1)

        if not is_empty(year) and int(year) < last_date.year:
            # year年份为上一年
            month_max = 12
            year_max = year
        else:
            # year 为本年
            month_max = last_date.month
            year_max = last_date.year

        months = [
            f"{year_max}-{'{:02d}'.format(month)}"
            for month in range(1, month_max + 1)
        ]

        return months


    def get_all_months(self, year=None):
        """
        根据年份，获取所有的月份数，方便前端展示一整年的情况
        """

        # 本月, 月初5个工作日后, 才会出上个月的账单数据
        current_date = datetime.datetime.today() - datetime.timedelta(days=7)
        # 上月, 只能查到上月的账单
        last_date = datetime.date(current_date.year, current_date.month, 1) - datetime.timedelta(days=1)

        month_max = 12
        if is_empty(year)  or int(year) >= last_date.year:
            year = last_date.year


        months = [
            f"{year}-{'{:02d}'.format(month)}"
            for month in range(1, month_max + 1)
        ]

        return months




    #
    # def put_budget_amount(self, bill_cycle, budget_amount, message):
    #     try:
    #         BillMonth.delete_cycle(bill_cycle)
    #         data = BillInstance.get_total_amount_for_month(bill_cycle)
    #         if not bool(data):
    #             data = {
    #                 "bill_cycle": bill_cycle,
    #                 "budget_amount": budget_amount,
    #                 "tax_budget": round(budget_amount / 1.06, 2),
    #                 "message": message
    #             }
    #         else:
    #             data["budget_amount"] = budget_amount
    #             data["tax_budget"] = round(budget_amount / 1.06, 2)
    #             data["message"] = message
    #
    #         BillMonth.add(data)
    #     except Exception as e:
    #         msg = f"put_budget_amount error => {e}"
    #         current_app.logger.error(msg)
    #         return False
    #
    #     current_app.logger.info(f"update_budget_amount bill_cycle:{bill_cycle}, budget_amount:{budget_amount} success")
    #     return True



    def update_from_instance(self, db: Session, bill_cycle):
        # 从账单实例表更新每个平台的月度表
        try:
            for cloud_platform in ["阿里云", "华为云"]:
                # 查找费用账单是否存在
                instance_data = BillInstance.get_instance_sum_for_cycle_platform(db, bill_cycle, cloud_platform)
                if not bool(instance_data):
                    logger.error(f"get_instance_sum_for_cycle_platform is None, cloud_platform:{cloud_platform}")
                    continue

                month_data = BillMonth.get_object_info_by_cycle_platform(db, bill_cycle, cloud_platform)
                if not month_data:
                    # 不存在，则添加
                    result = BillMonth.add(db, instance_data)
                    if not result:
                        logger.error(f"add bill month to database failed, cloud_platform:{cloud_platform}")
                        return False
                else:
                    # 存在，则更新
                    month_data.update(instance_data)
                    result = BillMonth.update(db, month_data)
                    if not result:
                        logger.error(f"update Bill Month to database failed, cloud_platform:{cloud_platform}")
                        return False
                logger.info(f"update Bill Month to database success, cloud_platform:{cloud_platform}")
        except Exception as e:
            msg = f"update_from_instance error => {e}"
            logger.exception(msg)
            return False

        logger.info(f"update_from_instance bill_cycle:{bill_cycle} success")
        return True
